package com.atguigu.tingshu.user.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import com.atguigu.tingshu.album.client.TrackInfoFeignClient;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.rabbit.constant.MqConst;
import com.atguigu.tingshu.common.rabbit.service.RabbitService;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.user.*;
import com.atguigu.tingshu.user.mapper.*;
import com.atguigu.tingshu.user.service.UserInfoService;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.atguigu.tingshu.vo.user.UserPaidRecordVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.joda.time.LocalDateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

	@Autowired
	private UserInfoMapper userInfoMapper;

	@Autowired
	private WxMaService wxMaService;

	@Autowired
	private RedisTemplate redisTemplate;

	@Autowired
	private RabbitService rabbitService;

	@Autowired
	private UserPaidAlbumMapper userPaidAlbumMapper;

	@Autowired
	private UserPaidTrackMapper userPaidTrackMapper;

	@Autowired
	private TrackInfoFeignClient trackInfoFeignClient;

	@Autowired
	private VipServiceConfigMapper vipServiceConfigMapper;

	@Autowired
	private UserVipServiceMapper userVipServiceMapper;

	/**
	 * @author WeakMoon
	 * @date 2025/02/23 21:51:18
	 * 微信登陆
	 */
	@Override
	public Map<String, Object> wxLogin(String code) {
	    // 创建一个Map对象用于存储登录结果
	    Map<String, Object> map = new HashMap<>();

	    // 声明一个微信会话信息结果对象
	    WxMaJscode2SessionResult wxMaJscode2SessionResult = null;

	    // 尝试使用微信提供的code换取会话信息
	    try {
			wxMaJscode2SessionResult = wxMaService.jsCode2SessionInfo(code);
	    } catch (WxErrorException e) {
	        // 如果发生错误，抛出运行时异常
	        throw new RuntimeException(e);
	    }

	    // 获取微信用户的唯一标识符
	    String openid = wxMaJscode2SessionResult.getOpenid();

	    // 查询数据库中是否存在对应的用户信息
	    UserInfo userInfo = userInfoMapper.selectOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getWxOpenId, openid));

	    // 如果用户信息不存在，则创建新用户
	    if (userInfo == null){
	        userInfo = new UserInfo();
	        userInfo.setWxOpenId(openid);
	        // 生成随机昵称
	        userInfo.setNickname("用户" + UUID.randomUUID().toString().replaceAll("-",""));
	        // 设置默认头像
	        userInfo.setAvatarUrl("https://oss.aliyuncs.com/aliyun_id_photo_bucket/default_handsome.jpg");
	        // 插入用户信息到数据库
	        userInfoMapper.insert(userInfo);
	        // 发送用户注册消息到消息队列
	        rabbitService.sendMessage(MqConst.EXCHANGE_USER, MqConst.ROUTING_USER_REGISTER, userInfo.getId());
	    }

	    // 生成用户登录令牌
	    String token = UUID.randomUUID().toString().replaceAll("-","");
	    // 构建Redis存储用户登录信息的键
	    String userLoginKey = RedisConstant.USER_LOGIN_KEY_PREFIX + token;
	    // 将用户信息存储到Redis中
	    redisTemplate.opsForValue().set(userLoginKey,userInfo,RedisConstant.USER_LOGIN_KEY_TIMEOUT, TimeUnit.SECONDS);
	    // 将令牌放入返回的Map中
	    map.put("token",token);
	    // 返回登录结果
	    return map;
	}

	/**
	 * @author WeakMoon
	 * @date 2025/02/25 17:11:32
	 * 获取用户信息
	 */
	@Override
	public UserInfoVo getUserInfo(Long userId) {
		//	查询数据
		UserInfo userInfo = this.getById(userId);

		//	属性拷贝：
		UserInfoVo userInfoVo = new UserInfoVo();
		BeanUtils.copyProperties(userInfo,userInfoVo);

		//	返回数据
		return userInfoVo;
	}

	/**
	 * @author WeakMoon
	 * @date 2025/02/25 17:11:56
	 * 修改用户信息
	 */
	@Override
	public void updateUserInfo(UserInfoVo userInfoVo, Long userId) {
		//	创建对象
		UserInfo userInfo = new UserInfo();

		//	属性拷贝：
		BeanUtils.copyProperties(userInfoVo,userInfo);
		userInfo.setId(userId);

		//	更新用户信息
		userInfoMapper.updateById(userInfo);
	}

	/**
	 * @author WeakMoon
	 * @date 2025/03/03 19:34:50
	 * 判断用户是否购买声音列表
	 */
	@Override
	public Map<Long, Integer> userIsPaidTrack(Long albumId, List<Long> trackIdList, Long userId) {
	    // 初始化一个空的HashMap用于存储声音ID和对应的购买状态
	    Map<Long, Integer> map = new HashMap<>();

	    // 检查用户是否购买了整个专辑
	    UserPaidAlbum userPaidAlbum = userPaidAlbumMapper.selectOne(new LambdaQueryWrapper<UserPaidAlbum>().eq(UserPaidAlbum::getUserId, userId).eq(UserPaidAlbum::getAlbumId, albumId));
	    if (userPaidAlbum != null) {
	        // 如果用户购买了专辑，则所有声音列表中的声音都视为已购买，直接返回1
	        return trackIdList.stream().collect(Collectors.toMap(track -> track, track -> 1));
	    } else {
	        // 如果用户未购买专辑，则检查用户是否购买了声音列表中的每个声音
	        LambdaQueryWrapper<UserPaidTrack> wrapper = new LambdaQueryWrapper<>();
	        wrapper.eq(UserPaidTrack::getUserId, userId).in(UserPaidTrack::getTrackId, trackIdList).eq(UserPaidTrack::getAlbumId, albumId);

	        // 获取用户购买的声音ID列表
	        List<Long> userPaidtrackIdList = userPaidTrackMapper.selectList(wrapper).stream().map(UserPaidTrack::getTrackId).collect(Collectors.toList());
	        // 遍历声音列表，判断每个声音是否被用户购买
	        for (Long trackId : trackIdList) {
	            if (userPaidtrackIdList.contains(trackId)) {
	                // 如果声音被购买，放入map中，值为1
	                map.put(trackId, 1);
	            } else {
	                // 如果声音未被购买，放入map中，值为0
	                map.put(trackId, 0);
	            }
	        }
	    }
	    // 返回包含所有声音购买状态的map
	    return map;
	}

	/**
	 * @author WeakMoon
	 * @date 2025/03/07 19:24:56
	 * 判断用户是否购买过专辑
	 */
	@Override
	public Boolean isPaidAlbum(Long albumId, Long userId) {
		//
		return null != userPaidAlbumMapper.selectOne(new LambdaQueryWrapper<UserPaidAlbum>().eq(UserPaidAlbum::getUserId,userId).eq(UserPaidAlbum::getAlbumId,albumId));
	}

	/**
	 * @author WeakMoon
	 * @date 2025/03/08 17:12:00
	 * 获取专辑已支付的声音Id集合列表
	 */
	@Override
	public List<Long> findUserPaidTrackList(Long albumId, Long userId) {
		//将select * from user_paid_track where user_id= 30 and album_id = 341转化代码;
		return userPaidTrackMapper.selectList(new LambdaQueryWrapper<UserPaidTrack>().eq(UserPaidTrack::getUserId,userId).eq(UserPaidTrack::getAlbumId,albumId)).stream().map(UserPaidTrack::getTrackId).collect(Collectors.toList());
	}

	/**
	 * @author WeakMoon
	 * @date 2025/03/10 18:37:05
	 * 处理用户购买记录
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public int savePaidRecord(UserPaidRecordVo userPaidRecordVo) {
		//声明一个变量
		int result = 0;
		//判断购买数据类型
		if (SystemConstant.ORDER_ITEM_TYPE_ALBUM.equals(userPaidRecordVo.getItemType())){
			//专辑
			//查询表中已有数据
			UserPaidAlbum userPaidAlbum = userPaidAlbumMapper.selectOne(new LambdaQueryWrapper<UserPaidAlbum>().eq(UserPaidAlbum::getUserId, userPaidRecordVo.getUserId()).eq(UserPaidAlbum::getAlbumId, userPaidRecordVo.getItemIdList().get(0)));
			//判断
			if (null != userPaidAlbum){
				//没有插入数据
				return result;
			}
			//创建一个对象
			userPaidAlbum = new UserPaidAlbum();
			//赋值
			userPaidAlbum.setUserId(userPaidRecordVo.getUserId());
			userPaidAlbum.setAlbumId(userPaidRecordVo.getItemIdList().get(0));
			userPaidAlbum.setOrderNo(userPaidRecordVo.getOrderNo());
			//保存数据
			return result += userPaidAlbumMapper.insert(userPaidAlbum);
		} else if (SystemConstant.ORDER_ITEM_TYPE_TRACK.equals(userPaidRecordVo.getItemType())){
			//声音
			//防止重复购买声音
			//购买的声音id
			List<Long> itemIdList = userPaidRecordVo.getItemIdList();
			//根据声音获取声音对象
			Result<TrackInfo> trackInfoResult = trackInfoFeignClient.getTrackInfo(itemIdList.get(0));
			Assert.notNull(trackInfoResult,"查询声音失败");
			TrackInfo trackInfo = trackInfoResult.getData();
			Assert.notNull(trackInfo,"查询声音失败！");
			//  查询当前用户是否购买过声音; select * from user_paid_track where user_id = 30 and track_id in (1,2,3);
			//  一样的就不需要插入数据; 可能涉及到退款；否则就插入数据！
			List<Long> userPaidTrackList = userPaidTrackMapper.selectList(new LambdaQueryWrapper<UserPaidTrack>().eq(UserPaidTrack::getUserId, userPaidRecordVo.getUserId()).eq(UserPaidTrack::getTrackId, itemIdList)).stream().map(UserPaidTrack::getTrackId).collect(Collectors.toList());
			//循环遍历
			for (Long trackId : itemIdList) {
				if (userPaidTrackList.contains(trackId)){
					//退款
					log.warn("退款" + trackId);
				} else {
					//插入了数据
					UserPaidTrack userPaidTrack = new UserPaidTrack();
					userPaidTrack.setUserId(userPaidRecordVo.getUserId());
					userPaidTrack.setTrackId(trackId);
					userPaidTrack.setOrderNo(userPaidRecordVo.getOrderNo());
					userPaidTrack.setAlbumId(trackInfo.getAlbumId());
					//保存数据
					result += userPaidTrackMapper.insert(userPaidTrack);
				}
			}
			return result;
		} else if (SystemConstant.ORDER_ITEM_TYPE_VIP.equals(userPaidRecordVo.getItemType())) {
			//VIP
			//考虑购买时长
			Long vipServiceConfigId = userPaidRecordVo.getItemIdList().get(0);
			//获取购买时间
			VipServiceConfig vipServiceConfig = vipServiceConfigMapper.selectById(vipServiceConfigId);
			Integer serviceMonth = vipServiceConfig.getServiceMonth();
			UserVipService userVipService = new UserVipService();
			//获取用户信息判断现在是不是VIP
			UserInfo userInfo = userInfoMapper.selectById(userPaidRecordVo.getUserId());
			Date vipExpireTime = new Date();
			//现在还是vip，续期
			if (1 == userInfo.getIsVip() && userInfo.getVipExpireTime().after(new Date())){
				//续期
				//获取原本过期时间
				vipExpireTime = userInfo.getVipExpireTime();
				//日期计算
				LocalDateTime localDateTime = new LocalDateTime(vipExpireTime).plusMonths(serviceMonth);
				vipExpireTime = localDateTime.toDate();
			} else {
				//购买
				vipExpireTime = new LocalDateTime(vipExpireTime).plusMonths(serviceMonth).toDate();
			}
			userVipService.setOrderNo(userPaidRecordVo.getOrderNo());
			userVipService.setUserId(userPaidRecordVo.getUserId());
			userVipService.setStartTime(new Date());
			//设置过期时间
			userVipService.setExpireTime(vipExpireTime);
			//保存数据
			result += userVipServiceMapper.insert(userVipService);
			//更改用户信息
			userInfo.setIsVip(1);
			userInfo.setVipExpireTime(vipExpireTime);
			result += userInfoMapper.updateById(userInfo);
		}
		return result;
	}
}
